#include "shmem.h"
#include <unistd.h>
#include <errno.h>
#include <string.h>

CShmem::CShmem(const string& name,unsigned int size,
            int flag,int mode)
    :m_name(name)
     ,m_fd(-1)
     ,m_flags(flag)
     ,m_mode(mode)
     ,m_size(size)
     ,m_addr(NULL)
{}

CShmem::~CShmem()
{
    if (m_fd > 0)
    {
        close(m_fd);
    }
    unmap();
}

bool CShmem::open()
{
    if (m_name.empty())
        return false;

    m_fd = shm_open(m_name.c_str(),m_flags, m_mode);
    bool bExist = false;
    if (m_fd < 0)
    {
        if (isOpened())
        {
            bExist = true;
            int tmp = m_flags & SH_CREAT;
            if ( tmp == SH_CREAT)
                m_flags -= SH_CREAT;
            
            m_fd = shm_open(m_name.c_str(),m_flags, m_mode);
            if (m_fd < 0)
                return false;
            
            return true;
        }
        return false;
    }
    
    if (ftruncate(m_fd,m_size) != 0)
        return false;

    return map(bExist);
}

bool CShmem::isOpened()
{
    if (m_name.empty())
        return false;

    int ret = shm_open(m_name.c_str(),SH_CREAT|SH_EXCL,USER_R|USER_W);
    if (ret < 0 && errno == EEXIST)
        return true;

    return false;
}

void CShmem::unlink()
{
    if (m_fd > 0)
    {
        close(m_fd);
        shm_unlink(m_name.c_str());
    }
}

bool CShmem::map(bool bExist)
{
    m_addr = mmap(NULL,m_size,PROT_READ|PROT_WRITE,
            MAP_SHARED,m_fd,0);

    if (m_addr == MAP_FAILED)
    {
        m_addr = NULL;
        return false;
    }
    
    // 共享已存在，不清除共享内存中的数据
    // 上G的共享内存，memset 会挂掉，可以考虑只初始化头部信息
    // if (!bExist)
    // {
    //     memset(m_addr,0,m_size);
    // }
    return true;
}

void CShmem::unmap()
{
    if (m_addr != NULL)
    {
        munmap(m_addr,m_size);
    }
}







